﻿using System;
using System.Linq;
using System.IO;
using LockerRack.Drawers;
using LockerRack.Exceptions;
using LockerRack.Helpers;
using LockerRack.Interfaces;
using Microsoft.Practices.Unity;
using NUnit.Framework;
using UIController;
using UIController.Controllers;

namespace TestFileController
{
    [TestFixture]
    public class LockerTests
    {
        private const string ROOT_FOLDER = @"d:\mine\sources\desktop\DropBoxToDo_codeplex\TestFileController\TestData\Locker";
        private const bool EXECUTE_TEAR_DOWN = false;
        
        [SetUp]
        public void Init()
        {
            PathUtility.CheckDirectory(ROOT_FOLDER);
        }

        [TearDown]
        public void TearDown()
        {
// ReSharper disable ConditionIsAlwaysTrueOrFalse
            if (!EXECUTE_TEAR_DOWN)
// ReSharper restore ConditionIsAlwaysTrueOrFalse
                return;

// ReSharper disable CSharpWarnings::CS0162
// ReSharper disable HeuristicUnreachableCode
            ClearLockerDirectory();
// ReSharper restore HeuristicUnreachableCode
// ReSharper restore CSharpWarnings::CS0162
        }

        private static void ClearLockerDirectory()
        {
            if (Directory.Exists(ROOT_FOLDER))
                Directory.Delete(ROOT_FOLDER, true);
        }

        [Test]
        public void TestOpenLocker()
        {
            LockerException ex;
            var controller = TaskModelController.GetInstance();
            controller.Initialize(ROOT_FOLDER, out ex);
            
            Assert.IsNull(ex);

            Create3SimpleDrawersAnd1InsidePlain(controller, out ex);
            Assert.IsNull(ex);

            var file = controller.Locker.Drawers[0].Files[0];
            var bag = file.Contents.PropertyBag;
            bag.IsCompleted = true;
            Guid guid = bag.GuidId;

            controller.Clear(true, out ex);
            Assert.IsNull(ex);

            controller.Initialize(ROOT_FOLDER, out ex);
            Assert.IsNull(ex);

            file = controller.Locker.FindFileById(guid);
            bag = file.Contents.PropertyBag;
            
            Assert.IsTrue(bag.IsCompleted);

            controller.Clear(true, out ex);
            Assert.IsNull(ex);
        }

        [Test]
        public void TestCloseLocker()
        {
            LockerException ex;
            var controller = TaskModelController.GetInstance();
            controller.Initialize(ROOT_FOLDER, out ex);

            Assert.IsNull(ex);

            Create3SimpleDrawersAnd1InsidePlain(controller, out ex);
            Assert.IsNull(ex);

            controller.Clear(true, out ex);
            Assert.IsNull(ex);

            var dirs = Directory.EnumerateDirectories(ROOT_FOLDER).Count();
            Assert.AreEqual(3, dirs);
        }

        [Test]
        public void TestMoveDrawerFile()
        {
            ClearLockerDirectory();

            LockerException ex;
            var controller = TaskModelController.GetInstance();
            controller.Initialize(ROOT_FOLDER, out ex);

            Assert.IsNull(ex, ex != null ? ex.Message : string.Empty);

            Create3SimpleDrawers(controller, out ex);

            var source = controller.Locker.Drawers[0];
            var file = source.Files[0];
            var target = controller.Locker.Drawers[1];
            var guid = file.Contents.Id;

            source.MoveDrawerFileTo(target, file, out ex);
            Assert.IsNull(ex, ex != null ? ex.Message : string.Empty);

            var found = source.FindFileById(guid);
            Assert.IsNull(found);

            found = target.FindFileById(guid);
            Assert.IsNotNull(found);

            controller.Clear(true, out ex);
            Assert.IsNull(ex, ex != null ? ex.Message : string.Empty);
        }

        [Test]
        public void TestMoveDrawerFile1()
        {
            ClearLockerDirectory();

            LockerException ex;
            var controller = TaskModelController.GetInstance();
            controller.Initialize(ROOT_FOLDER, out ex);

            Assert.IsNull(ex, ex != null ? ex.Message : string.Empty);

            Create3SimpleDrawers(controller, out ex);

            var source = controller.Locker.Drawers[0];
            var file = source.Files[0];
            var target = controller.Locker.Drawers[1];
            var guid = file.Contents.Id;

            source.MoveDrawerFileByIdTo(target, file, out ex);
            Assert.IsNull(ex, ex != null ? ex.Message : string.Empty);

            var found = source.FindFileById(guid);
            Assert.IsNull(found);

            found = target.FindFileById(guid);
            Assert.IsNotNull(found);

            controller.Clear(true, out ex);
            Assert.IsNull(ex, ex != null ? ex.Message : string.Empty);
        }

        private void Create3SimpleDrawers(ITaskController controller, out LockerException lex)
        {
            lex = null;
            for (int i = 0; i < 3; i++)
            {
                var d = new Drawer();
                DrawerFile file = CreateDrawerFile("Test", controller, out lex);

                d.Files.Add(file);

                controller.Locker.Drawers.Add(d);
            }
        }

        private void Create3SimpleDrawersAnd1InsidePlain(ITaskController controller, out LockerException lex)
        {
            var d = new Drawer { Name = "Root" };
            DrawerFile file = CreateDrawerFile("Root file", controller, out lex);

            d.Files.Add(file);

            controller.Locker.Drawers.Add(d);

            var d1 = new Drawer { Name = "Root Child 1" };
            DrawerFile file1 = CreateDrawerFile("Root Child 1 file", controller, out lex);

            d1.Files.Add(file1);
            d.AddChild(d1);

            var d2 = new Drawer { Name = "Root Child 2" };
            DrawerFile file2 = CreateDrawerFile("Root Child 2 file", controller, out lex);
            d2.Files.Add(file2);

            d.AddChild(d2);

            var d3 = new Drawer { Name = "Root Child 2 Child" };
            DrawerFile file3 = CreateDrawerFile("Root Child 2 child file", controller, out lex);
            d3.Files.Add(file3);

            d2.AddChild(d3);

            d = new Drawer { Name = "Root 1" };
            file = CreateDrawerFile("Root 1 file", controller, out lex);

            d.Files.Add(file);

            controller.Locker.Drawers.Add(d);

            d1 = new Drawer { Name = "Root 1 Child 1" };
            file1 = CreateDrawerFile("Root 1 Child 1 file", controller, out lex);

            d1.Files.Add(file1);
            d.AddChild(d1);

            d2 = new Drawer { Name = "Root 1 Child 2" };
            file2 = CreateDrawerFile("Root 1 Child 2 file", controller, out lex);
            d2.Files.Add(file2);

            d.AddChild(d2);

            d3 = new Drawer { Name = "Root 1 Child 2 Child" };
            file3 = CreateDrawerFile("Root 1 Child 2 Child file", controller, out lex);
            d3.Files.Add(file3);

            d2.AddChild(d3);
        }

        private DrawerFile CreateDrawerFile(string name, ITaskController controller,  out LockerException lex)
        {
            var file = new DrawerFile(controller.TypesContainer);
            file.Name = name;
            file.Filename = "Filename.xml";

            var resolver = controller.TypesContainer.Resolve<IDrawerFileResolver>();

            var stuff = resolver.CreateDefaultContent();
            file.CreateNewContent(stuff, out lex);
            stuff.PropertyBag.Desc = name;
            stuff.PropertyBag.Note = name;
            return file;
        }
    }
}
